﻿using System;
using System.Collections.Generic;
using System.Windows;

namespace AdTech.Snap.Interop
{
    /// <summary>
    /// Win32 API Helper for getting monitor information.
    /// </summary>
    public static class MonitorInteropHelper
    {
        // Fields
        private const int MONITOR_DEFAULTTONULL = 0x00000000;
        private const int MONITOR_DEFAULTTOPRIMARY = 0x00000001;
        private const int MONITOR_DEFAULTTONEAREST = 0x00000002;

        // Methods
        /// <summary>
        /// Returns a rectangle of the entire screen boundaries.
        /// </summary>
        /// <remarks>
        /// The rectangle is not relative to the primary screen, thus 0.0 will be on 
        /// the first monitor which is on the very left independent on multi-monitor setup.
        /// </remarks>
        /// <param name="relative">
        /// Due to different multi monitor setups it may be that some boundaries are negative. 
        /// Only the window itself has to deal with this position.
        /// The child rectangle itself is relative to the window.
        /// Pass true if the child rectangle, or false if the screen boundaries should be returned.
        /// </param>
        /// <returns>A <see cref="System.Windows.Rect"/> structure of the screen boundaries.</returns>
        public static Rect GetTotalScreenBoundaries(bool relative = false)
        {
            int x = NativeMethods.GetSystemMetrics(SystemMetric.SM_XVIRTUALSCREEN);
            int y = NativeMethods.GetSystemMetrics(SystemMetric.SM_YVIRTUALSCREEN);
            int w = NativeMethods.GetSystemMetrics(SystemMetric.SM_CXVIRTUALSCREEN);
            int h = NativeMethods.GetSystemMetrics(SystemMetric.SM_CYVIRTUALSCREEN);
            return relative ? new Rect(new Size(w, h)) : new Rect(x, y, w, h);
        }

        /// <summary>
        /// Gets information about the monitor on which the given window lies.
        /// </summary>
        /// <param name="handle">The handle of the window.</param>
        /// <returns>A <see cref="AdTech.Snap.Interop.DisplayInfo"/> structure containing display information.</returns>
        internal static DisplayInfo GetDisplayFromWindow(IntPtr handle)
        {
            return GetDisplay(NativeMethods.MonitorFromWindow(handle, MONITOR_DEFAULTTONULL));
        }

        /// <summary>
        /// Gets information about a given monitor.
        /// </summary>
        /// <param name="handle">The handle of the monitor.</param>
        /// <returns>A <see cref="AdTech.Snap.Interop.DisplayInfo"/> structure containing display information.</returns>
        private static DisplayInfo GetDisplay(IntPtr handle)
        {
            MONITORINFO mi = new MONITORINFO();
            mi.Init();
            NativeMethods.GetMonitorInfo(handle, ref mi);
            return mi;
        }
    }
}
